package cn.weiyan.dtx.txmsgdemo.bank1.txlistener;

import cn.weiyan.dtx.txmsgdemo.bank1.dao.AccountInfoDao;
import cn.weiyan.dtx.txmsgdemo.bank1.model.AccountChangeEvent;
import cn.weiyan.dtx.txmsgdemo.bank1.server.AccountInfoService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;

/**
 * @author misterWei
 * @create 2020年02月16号:12点36分
 * @mailbox mynameisweiyan@gmail.com
 *
 * 该方法是rocketMq提供的支持执行本地事务执行,以及对事务进行状态检查.
 *
 */
@Service
@Slf4j
@RocketMQTransactionListener(txProducerGroup = "producer_txmsg_bank1")
public class TxMessageListener implements RocketMQLocalTransactionListener{

    @Autowired
    private AccountInfoDao accountInfoDao;

    @Autowired
    private AccountInfoService accountInfoService;

    /**
     * 该方法用来执行本地事务,
     * 如果返回的状态是成功,就把消息标记为可消费,
     * 否则就把该消息删除.消费方就接受不到消息
     * @param message
     * @param o
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        try {

            Object messageByte = message.getPayload();
            String messageString = new String((byte []) messageByte);
            AccountChangeEvent accountChangeEvent = JSON.parseObject(messageString, AccountChangeEvent.class);
            accountInfoService.doUpdateAccountBalance(accountChangeEvent);
            return RocketMQLocalTransactionState.COMMIT;
        }catch (Exception e){
            log.error("错误原因 : "+ e.getMessage());
            return RocketMQLocalTransactionState.ROLLBACK;
        }


    }

    /**
     * 该方法用来检查事务的执行状态,这里我们使用幂等性的思想去解决.
     * @param message
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        //幂等性判断
        Object messageByte = message.getPayload();
        String messageString = new String((byte []) messageByte);
        AccountChangeEvent accountChangeEvent = JSON.parseObject(messageString, AccountChangeEvent.class);
        String txNo = accountChangeEvent.getTxNo();
        int existTx = accountInfoDao.isExistTx(txNo);
        if (existTx >0){
            return RocketMQLocalTransactionState.COMMIT;
        }else{
            return RocketMQLocalTransactionState.UNKNOWN;
        }

    }
}
